Skip to content

fix(libc): end the process without detach routines in _Exit on Windows - #2612

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
oneandonlydean:fix/carry-2579
Oct 10, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
oneandonlydean:fix/carry-2579

Conversation

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Carrying @AlxcBTW's fix for #2579 while PR intake is paused. The change is theirs (from AlxcBTW/AnyPS5:fix/windows-immediate-exit, 2feef9e).

What

_Exit (libc) and _exit (libkernel) end the process through LibcTerminate_nid_no_patch, which calls TerminateProcess on Windows and std::_Exit elsewhere.

Why

On Windows std::_Exit ends in ExitProcess, which still runs every module's DLL_PROCESS_DETACH and its TLS and FLS callbacks after the other threads are gone. FlipQueue's destructor then joins a thread that no longer exists and waits forever. Homebrew UI Lab (PPSA99050) calls _Exit(EXIT_FAILURE) after

submission retirement failed

and the process stays alive, with one thread in std::_Sp_counted_ptr_inplace<FlipQueue>::_M_dispose (libSceVideoOut.prx) waiting in std::thread::join. POSIX _exit runs no atexit handlers, stream flushes or module destructors.

Tested

  • The author's full CI with the change merged into main c72d5ce passes on Linux, macOS and Windows.
  • guest_immediate_exit now also registers an FLS callback that would end the process with 4. It exits with 4 without the change and 0 with it. ctest -R "kill|exit|process|shutdown|atexit|libc|kernel": 19/19.
  • UI Lab now exits with 1 (EXIT_FAILURE) instead of staying alive.
  • tools/check_conventions.py passes, and the branch merges cleanly with current main.

Fixes #2579

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • AI-assisted: yes

On Windows std::_Exit ends in ExitProcess, which still runs every module's
DLL_PROCESS_DETACH and TLS callbacks after the other threads are gone. A
static destructor that joins a worker then waits forever: a title that calls
_Exit while libSceVideoOut's flip queue runs (ps5-opengl's retirement
fail-stop) stays alive in FlipQueue's destructor. _Exit and libkernel's _exit
now terminate the process with TerminateProcess, as _exit ends a POSIX
process: no atexit handlers, stream flushes or module destructors.
@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
#1525 core/libs/tests/GuestSystemExit.cpp L7, L29

@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the diff (_Exit and _exit now share LibcTerminate_nid_no_patch, TerminateProcess on Windows, std::_Exit elsewhere), build and ctest on Linux (126/126 in libs, libc, libkernel). The new FLS check in guest_immediate_exit is _WIN32 only; the Windows result relies on the full CI run reported in the description. Merging.

@adriadam10
adriadam10 merged commit 919c49b into boykopovar:main Oct 10, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows: guest _Exit hangs in FlipQueue's destructor because ExitProcess still runs module detach routines

3 participants